﻿using System;
using System.Xml;
using System.IO;
using System.Collections;


using Google.GData.AccessControl;
using Google.GData.Calendar;
using Google.GData.Client;
using Google.GData.Extensions;

namespace GCalendar
{    
    public class GCalendar
    {
        static string UserName, UserPassword;
        static Hashtable HashCalendarList = new Hashtable();
        static bool HasAuthened = false;
        static CalendarService GCalendarService = new CalendarService("MyGoogleCalender");
        public GCalendar()
        {
            if (! HasAuthened)
            {
                throw new Exception("Authentication Failed");
            }
        }
        public static bool UserAuthen(string UserNameStr, string UserPassWordStr)
        {
            bool ret;
            GCalendarService.setUserCredentials(UserNameStr, UserPassWordStr);
            try
            {
                GCalendarService.QueryAuthenticationToken();
                ret = true;
                UserName = UserNameStr;
                UserPassword = UserNameStr;

                GetCalendarList();
            }
            catch
            {
                ret = false;
            }
            HasAuthened  = ret;

            return ret;
        }
        protected static void GetCalendarList()
        {
            HashCalendarList.Clear();
            CalendarQuery Gquery = new CalendarQuery();
            Gquery.Uri = new Uri("http://www.google.com/calendar/feeds/default/allcalendars/full");
            CalendarFeed resultFeed = GCalendarService.Query(Gquery);
            foreach ( CalendarEntry _Entry in resultFeed.Entries)
            {
                HashCalendarList.Add(_Entry.Title.Text, _Entry.Content.AbsoluteUri);
            }
        }
        public string[] CalendarList()
        {
            string[] ret = new string[HashCalendarList.Count];
            HashCalendarList.Keys.CopyTo(ret, 0);
            return ret;
        }
        #region GetEventlist
        protected EventEntry[] GETEnventList(string CalendarKey, DateTime _StartTime, DateTime _EndTime)
        {
            EventQuery _EnventQuery = new EventQuery(HashCalendarList[CalendarKey].ToString());
            
           // if (_StartTime != DateTime.MinValue) 
            _EnventQuery.StartTime = _StartTime;
           // if(_EndTime != DateTime .MaxValue )
            _EnventQuery.EndTime = _EndTime;

            EventFeed ResultsFeed = GCalendarService.Query(_EnventQuery);
            EventEntry[] EventEntryList = new EventEntry[ResultsFeed .Entries .Count];
            
            ResultsFeed .Entries.CopyTo(EventEntryList ,0);
            return EventEntryList;
                            
        }
        public EventEntry[] GETEnventList(string CalendarKey, DateTime _StartTime)
        {
            return this.GETEnventList(CalendarKey, _StartTime, DateTime.MaxValue);
        }
        public EventEntry[] GETEnventList(string CalendarKey)
        {
            return this.GETEnventList(CalendarKey, DateTime.MinValue, DateTime.MaxValue);
        }
        #endregion
        public static string GetCurrenceInfo(string CurrenceStr)
        {
            char[] aa = "\r\n".ToCharArray();
            string[] Cur = CurrenceStr.Replace("\n","").Split("\r".ToCharArray ());
            return Cur.Length.ToString ();
        }

        public static bool AddEvent(EventEntry _item)
        {
            object o = new object();
            if (HasAuthened)
            {
                Service _insertServ = new Service();
                string url = HashCalendarList["test"].ToString();
                //url = "http://www.google.com/calendar/feeds/fsiiugene5cqcoij3n0r2i1068@group.calendar.google.com/private/full?gsessionid=yGc7lBKyu8F9Qp9ILxc2Bw";
                GCalendarService.Insert(new Uri(url), _item);
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool AddEvent(EventEntry _item, string calName)
        {
            object o = new object();
            if (HasAuthened)
            {
                Service _insertServ = new Service();
                string url = HashCalendarList[calName].ToString();
                GCalendarService.Insert(new Uri(url), _item);
                return true;
            }
            else
            {
                return false;
            }
        }

        public static void SaveCals()
        {
            CalendarQuery Gquery = new CalendarQuery();
            //Gquery.Uri = new Uri("http://www.google.com/calendar/feeds/default/allcalendars/full");
            Gquery.Uri = new Uri(@"http://www.google.com/calendar/feeds/gkmnblaj6hgo37dm4d3dj43634%40group.calendar.google.com/private/full");
            CalendarFeed resultFeed = GCalendarService.Query(Gquery);
            foreach ( CalendarEntry _Entry in resultFeed.Entries)
            {

                FileStream fs = new FileStream(@"C:\" + _Entry.Title.Text + ".xml", FileMode.Create);
                _Entry.Content.SaveToXml(fs);
                fs.Flush();
                fs.Close();


//                 FileStream fs = new FileStream(@"C:\" + _Entry.Title.Text + ".xml", FileMode.Create); 
//                 //XmlWriter w = XmlWriter.Create(fs);
//                 _Entry.Content.SaveToXml(fs);
//                 //_Entry.SaveToXml(fs);
//                 //w.Flush();
//                 //w.Close();
//                 fs.Flush();
//                 fs.Close();
            }
        }
        public static string GetiCalAdd(string CalName)
        {
            object o = new object();
            if (HasAuthened)
            {
                Service _insertServ = new Service();
                string url = HashCalendarList[CalName].ToString();
                Console.WriteLine(url);
                url = url.Replace("feeds", "ical");
                url = url.Trim() + ".ics";
                Console.WriteLine(url);
                // Trying with private add: Working fine
                url = @"http://www.google.com/calendar/ical/gkmnblaj6hgo37dm4d3dj43634%40group.calendar.google.com/private-c08237d812855d5f6111aa734eca8cdb/basic.ics";
                Console.WriteLine(url);
                // Trying with oublic add:
                url = @"http://www.google.com/calendar/ical/gkmnblaj6hgo37dm4d3dj43634%40group.calendar.google.com/private/basic.ics";
                System.Net.WebClient wc = new System.Net.WebClient();
                Console.WriteLine(url);
                wc.DownloadFile(url, @"c:\bentley1.ics");
                Console.WriteLine(url);
                Console.ReadKey();
                return url;
            }
            else
            {
                return "";
            }
        }

        public struct ReminderMethodConvent
        {
            Reminder.ReminderMethod RMethodName;
            public static string GetReminderDescription(Reminder.ReminderMethod ReminderMethodName)
            {
                string ret;
                switch (ReminderMethodName)
                {
                    case Reminder.ReminderMethod.alert:
                        ret = "弹出式窗口";
                        break;
                    case Reminder.ReminderMethod.email:
                        ret = "电子邮件";
                        break;
                    case Reminder.ReminderMethod.sms:
                        ret = "短信";
                        break;
                    case Reminder .ReminderMethod .all:
                        ret = "全部";
                        break;
                    case Reminder .ReminderMethod .none:                    
                    case Reminder .ReminderMethod .unspecified:
                        ret = "未指定";
                        break;
                    default:
                        ret = "未知";
                        break;
                }
                return ret;
            }
            public static Reminder.ReminderMethod GetReminderName(string ReminderMethodDescription)
            {
                Reminder.ReminderMethod ret;
                switch (ReminderMethodDescription)
                {
                    case "弹出式窗口":
                        ret = Reminder.ReminderMethod.alert;
                        break;
                    case  "电子邮件":
                        ret = Reminder.ReminderMethod.email;
                        break;
                    case  "短信":
                        ret  = Reminder.ReminderMethod.sms;
                        break;
                    case "全部":
                        ret = Reminder.ReminderMethod.all;
                        break;
                    default:
                        ret = Reminder.ReminderMethod.none;
                        break;
                }
                return ret;
            }
            public static string[] GetReminderDescriptionList()
            {
                string[] ret = { "弹出式窗口", "电子邮件", "短信", "全部", "未指定" };
                return ret;
            }
            public static string[] GetReminderNameList()
            {
                return Enum.GetNames(typeof(Reminder.ReminderMethod));
            }
            public Reminder.ReminderMethod RMethod
            {
                set {
                    RMethodName = value;
                }
                get {
                    return RMethodName;
                }
            }
            public string ReminderMethodDescription
            {
                get
                {
                    return ReminderMethodConvent.GetReminderDescription(RMethodName);
                }
            }
            public static string[] GetReminderTimeUnitList()
            {
                string[] ret = {"天", "小时", "分钟"};
                return ret;
            }
            public static DateTime GetAbsoluteTime(DateTime _TimeBase, string _TimeUint, int _TimeSpan)
            {
                DateTime ret;
                TimeSpan TimeLen;
                switch (_TimeUint)
                {
                    case "天":
                        TimeLen = new TimeSpan(_TimeSpan, 0, 0, 0);
                        break;
                    case "小时":
                        TimeLen = new TimeSpan(_TimeSpan, 0, 0);
                        break;
                    case "分钟":
                        TimeLen = new TimeSpan(0, _TimeSpan, 0);
                        break;
                    default :
                        TimeLen = new TimeSpan(0, 0, 0);
                        break;
                }
                ret = _TimeBase.Add(TimeLen);
                return ret;
            }
        }
    }
    
    
    public class Event
    {
        public Google.GData.Calendar.EventEntry Item;
        public Event(string CalName, string EventName)
        {
            Item = new EventEntry();

            Item.Title.Text = EventName;

            When w = new When();
            w.StartTime = DateTime.Now;
            w.EndTime = DateTime.Now;

            Item.Times.Add(w);
            Item.Reminders.Clear();
            //             Reminder _r = new Reminder();
            //             _r.Minutes = 10;
            //             _r.Method = Reminder.ReminderMethod.email;
            //             Item.Reminders.Add(_r);
        }
    }
}
//string UserNameStr, string UserPassWordStr, bool SaveForever
//    class CalendarDemo
//    {
//        private static String userName, userPassword, feedUri;

//        /// <summary>
//        /// Prints a list of the user's calendars.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        static void PrintUserCalendars(CalendarService service)
//        {
//            FeedQuery query = new FeedQuery();
//            query.Uri = new Uri("http://www.google.com/calendar/feeds/default");

//            // Tell the service to query:
//            AtomFeed calFeed = service.Query(query);

//            Console.WriteLine("Your calendars:");
//            Console.WriteLine();
//            for (int i = 0; i < calFeed.Entries.Count; i++)
//            {
//                Console.WriteLine(calFeed.Entries[i].Title.Text);
//            }
//            Console.WriteLine();
//        }

//        /// <summary>
//        /// Prints the titles of all events on the specified calendar.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        static void PrintAllEvents(CalendarService service)
//        {
//            EventQuery myQuery = new EventQuery(feedUri);
//            EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;

//            Console.WriteLine("All events on your calendar:");
//            Console.WriteLine();
//            for (int i = 0; i < myResultsFeed.Entries.Count; i++)
//            {
//                Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
//            }
//            Console.WriteLine();
//        }

//        /// <summary>
//        /// Prints the titles of all events matching a full-text query.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="queryString">The text for which to query.</param>
//        static void FullTextQuery(CalendarService service, String queryString)
//        {
//            EventQuery myQuery = new EventQuery(feedUri);
//            myQuery.Query = queryString;

//            EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;

//            Console.WriteLine("Events matching \"{0}\":", queryString);
//            Console.WriteLine();
//            for (int i = 0; i < myResultsFeed.Entries.Count; i++)
//            {
//                Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
//            }
//            Console.WriteLine();
//        }

//        /// <summary>
//        /// Prints the titles of all events in a specified date/time range.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="startTime">Start time (inclusive) of events to print.</param>
//        /// <param name="endTime">End time (exclusive) of events to print.</param>
//        static void DateRangeQuery(CalendarService service, DateTime startTime, DateTime endTime)
//        {
//            EventQuery myQuery = new EventQuery(feedUri);
//            myQuery.StartTime = startTime;
//            myQuery.EndTime = endTime;

//            EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;

//            Console.WriteLine("Matching events from {0} to {1}:",
//                              startTime.ToShortDateString(),
//                              endTime.ToShortDateString());
//            Console.WriteLine();
//            for (int i = 0; i < myResultsFeed.Entries.Count; i++)
//            {
//                Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
//            }
//            Console.WriteLine();
//        }

//        /// <summary>
//        /// Helper method to create either single-instance or recurring events.
//        /// For simplicity, some values that might normally be passed as parameters
//        /// (such as author name, email, etc.) are hard-coded.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="entryTitle">Title of the event to create.</param>
//        /// <param name="recurData">Recurrence value for the event, or null for
//        ///                         single-instance events.</param>
//        /// <returns>The newly-created EventEntry on the calendar.</returns>
//        static EventEntry CreateEvent(CalendarService service, String entryTitle,
//                                     String recurData)
//        {
//            EventEntry entry = new EventEntry();

//            // Set the title and content of the entry.
//            entry.Title.Text = entryTitle;
//            entry.Content.Content = "Meet for a quick lesson.";

//            // Set a location for the event.
//            Where eventLocation = new Where();
//            eventLocation.ValueString = "South Tennis Courts";
//            entry.Locations.Add(eventLocation);

//            // If a recurrence was requested, add it.  Otherwise, set the
//            // time (the current date and time) and duration (30 minutes)
//            // of the event.
//            if (recurData == null)
//            {
//                When eventTime = new When();
//                eventTime.StartTime = DateTime.Now;
//                eventTime.EndTime = eventTime.StartTime.AddMinutes(30);
//                entry.Times.Add(eventTime);
//            }
//            else
//            {
//                Recurrence recurrence = new Recurrence();
//                recurrence.Value = recurData;
//                entry.Recurrence = recurrence;
//            }

//            // Send the request and receive the response:
//            Uri postUri = new Uri(feedUri);
//            AtomEntry insertedEntry = service.Insert(postUri, entry);

//            return (EventEntry)insertedEntry;
//        }

//        /// <summary>
//        /// Creates a single-instance event on a calendar.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="entryTitle">Title of the event to create.</param>
//        /// <returns>The newly-created EventEntry on the calendar.</returns>
//        static EventEntry CreateSingleEvent(CalendarService service, String entryTitle)
//        {
//            return CreateEvent(service, entryTitle, null);
//        }

//        /// <summary>
//        /// Creates a recurring event on a calendar. In this example, the event
//        /// occurs every Tuesday from May 1, 2007 through September 4, 2007. Note
//        /// that we are using iCal (RFC 2445) syntax; see http://www.ietf.org/rfc/rfc2445.txt
//        /// for more information.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="entryTitle">Title of the event to create.</param>
//        /// <returns>The newly-created EventEntry on the calendar.</returns>
//        static EventEntry CreateRecurringEvent(CalendarService service, String entryTitle)
//        {
//            String recurData =
//              "DTSTART;VALUE=DATE:20070501\r\n" +
//              "DTEND;VALUE=DATE:20070502\r\n" +
//              "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";

//            return CreateEvent(service, entryTitle, recurData);
//        }

//        /// <summary>
//        /// Updates the title of an existing calendar event.
//        /// </summary>
//        /// <param name="entry">The event to update.</param>
//        /// <param name="newTitle">The new title for this event.</param>
//        /// <returns>The updated EventEntry object.</returns>
//        static EventEntry UpdateTitle(EventEntry entry, String newTitle)
//        {
//            entry.Title.Text = newTitle;
//            return (EventEntry)entry.Update();
//        }

//        /// <summary>
//        /// Adds a reminder to a calendar event.
//        /// </summary>
//        /// <param name="entry">The event to update.</param>
//        /// <param name="numMinutes">Reminder time, in minutes.</param>
//        /// <returns>The updated EventEntry object.</returns>
//        static EventEntry AddReminder(EventEntry entry, int numMinutes)
//        {
//            Reminder reminder = new Reminder();
//            reminder.Minutes = numMinutes;
//            entry.Reminder = reminder;

//            return (EventEntry)entry.Update();
//        }

//        /// <summary>
//        /// Adds an extended property to a calendar event.
//        /// </summary>
//        /// <param name="entry">The event to update.</param>
//        /// <returns>The updated EventEntry object.</returns>
//        static EventEntry AddExtendedProperty(EventEntry entry)
//        {
//            ExtendedProperty property = new ExtendedProperty();
//            property.Name = "http://www.example.com/schemas/2005#mycal.id";
//            property.Value = "1234";

//            entry.ExtensionElements.Add(property);

//            return (EventEntry)entry.Update();
//        }

//        /// <summary>
//        /// Retrieves and prints the access control lists of all
//        /// of the authenticated user's calendars.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        static void RetrieveAcls(CalendarService service)
//        {
//            FeedQuery query = new FeedQuery();
//            query.Uri = new Uri("http://www.google.com/calendar/feeds/default");
//            AtomFeed calFeed = service.Query(query);

//            Console.WriteLine();
//            Console.WriteLine("Sharing permissions for your calendars:");

//            // Retrieve the meta-feed of all calendars.
//            foreach (AtomEntry calendarEntry in calFeed.Entries)
//            {
//                Console.WriteLine("Calendar: {0}", calendarEntry.Title.Text);
//                AtomLink link = calendarEntry.Links.FindService(
//                    AclNameTable.LINK_REL_ACCESS_CONTROL_LIST, null);

//                // For each calendar, retrieve its ACL feed.
//                if (link != null)
//                {
//                    AclFeed feed = service.Query(new AclQuery(link.HRef.ToString()));
//                    foreach (AclEntry aclEntry in feed.Entries)
//                    {
//                        Console.WriteLine("\tScope: Type={0} ({1})", aclEntry.Scope.Type,
//                            aclEntry.Scope.Value);
//                        Console.WriteLine("\tRole: {0}", aclEntry.Role.Value);
//                    }
//                }
//            }
//        }

//        /// <summary>
//        /// Shares a calendar with the specified user.  Note that this method
//        /// will not run by default.
//        /// </summary>
//        /// <param name="service">The authenticated CalendarService object.</param>
//        /// <param name="aclFeedUri">the ACL feed URI of the calendar being shared.</param>
//        /// <param name="userEmail">The email address of the user with whom to share.</param>
//        /// <param name="role">The role of the user with whom to share.</param>
//        /// <returns>The AclEntry returned by the server.</returns>
//        static AclEntry AddAccessControl(CalendarService service, string aclFeedUri,
//            string userEmail, AclRole role)
//        {
//            AclEntry entry = new AclEntry();

//            entry.Scope = new AclScope();
//            entry.Scope.Type = AclScope.SCOPE_USER;
//            entry.Scope.Value = userEmail;

//            entry.Role = role;

//            Uri aclUri =
//                new Uri("http://www.google.com/calendar/feeds/gdata.ops.test@gmail.com/acl/full");

//            AclEntry insertedEntry = service.Insert(aclUri, entry);
//            Console.WriteLine("Added user {0}", insertedEntry.Scope.Value);

//            return insertedEntry;
//        }

//        /// <summary>
//        /// Updates a user to have new access permissions over a calendar.
//        /// Note that this method will not run by default.
//        /// </summary>
//        /// <param name="entry">An existing AclEntry representing sharing permissions.</param>
//        /// <param name="newRole">The new role (access permissions) for the user.</param>
//        /// <returns>The updated AclEntry.</returns>
//        static AclEntry UpdateEntry(AclEntry entry, AclRole newRole)
//        {
//            entry.Role = newRole;
//            AclEntry updatedEntry = entry.Update() as AclEntry;

//            Console.WriteLine("Updated {0} to have role {1}", updatedEntry.Scope.Value,
//                entry.Role.Value);
//            return updatedEntry;
//        }

//        /// <summary>
//        /// Deletes a user from a calendar's access control list, preventing
//        /// that user from accessing the calendar.  Note that this method will
//        /// not run by default.
//        /// </summary>
//        /// <param name="entry">An existing AclEntry representing sharing permissions.</param>
//        static void DeleteEntry(AclEntry entry)
//        {
//            entry.Delete();
//        }

//        /// <summary>
//        /// Runs the methods above to demonstrate usage of the .NET
//        /// client library.  The methods that add, update, or remove
//        /// users on access control lists will not run by default.
//        /// </summary>
//        static void RunSample()
//        {
//            CalendarService service = new CalendarService("exampleCo-exampleApp-1");
//            service.setUserCredentials(userName, userPassword);

//            // Demonstrate retrieving a list of the user's calendars.
//            PrintUserCalendars(service);

//            // Demonstrate various feed queries.
//            PrintAllEvents(service);
//            FullTextQuery(service, "Tennis");
//            DateRangeQuery(service, new DateTime(2007, 1, 5), new DateTime(2007, 1, 7));

//            // Demonstrate creating a single-occurrence event.
//            EventEntry singleEvent = CreateSingleEvent(service, "Tennis with Mike");
//            Console.WriteLine("Successfully created event {0}", singleEvent.Title.Text);

//            // Demonstrate creating a recurring event.
//            AtomEntry recurringEvent = CreateRecurringEvent(service, "Tennis with Dan");
//            Console.WriteLine("Successfully created recurring event {0}", recurringEvent.Title.Text);

//            // Demonstrate updating the event's text.
//            singleEvent = UpdateTitle(singleEvent, "Important meeting");
//            Console.WriteLine("Event's new title is {0}", singleEvent.Title.Text);

//            // Demonstrate adding a reminder.  Note that this will only work on a primary
//            // calendar.
//            singleEvent = AddReminder(singleEvent, 15);
//            Console.WriteLine("Set a {0}-minute reminder for the event.", singleEvent.Reminder.Minutes);

//            // Demonstrate adding an extended property.
//            AddExtendedProperty(singleEvent);

//            // Demonstrate deleting the item.
//            singleEvent.Delete();

//            // Demonstrate retrieving access control lists for all calendars.
//            RetrieveAcls(service);
//        }

//        static void Main(string[] args)
//        {
//            if (args.Length != 3)
//            {
//                Console.WriteLine("Usage: gcal_demo <username> <password> <feedUri>");
//            }
//            else
//            {
//                userName = args[0];
//                userPassword = args[1];
//                feedUri = args[2];

//                RunSample();
//            }
//        }
//    }
//}

